package com.jfirer.validator.util;

import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.validation.ValidationException;
import javax.validation.metadata.PropertyDescriptor;
import com.jfirer.validator.PropertyValueDescriptor;
import com.jfirer.validator.PropertyValueDescriptorFactory;
import com.jfirer.baseutil.StringUtil;

public class ReflectPropertyValueDescriptorFactory implements PropertyValueDescriptorFactory
{
	private final ConcurrentMap<PropertyDescriptor, PropertyValueDescriptor> store = new ConcurrentHashMap<PropertyDescriptor, PropertyValueDescriptor>();
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jfireframework.validator.PropertyValueDescriptorFactory#getInstance(
	 * java.lang.Class, javax.validation.metadata.PropertyDescriptor)
	 */
	@Override
	public PropertyValueDescriptor getInstance(Class<?> beanType, PropertyDescriptor propertyDescriptor)
	{
		PropertyValueDescriptor propertyValueDescriptor = store.get(propertyDescriptor);
		if (propertyValueDescriptor == null)
		{
			synchronized (propertyDescriptor)
			{
				propertyValueDescriptor = store.get(propertyDescriptor);
				if (propertyValueDescriptor == null)
				{
					propertyValueDescriptor = new FieldPropertyValueDescriptor();
					propertyValueDescriptor.initialize(beanType, propertyDescriptor.getPropertyName());
					store.put(propertyDescriptor, propertyValueDescriptor);
				}
			}
		}
		return propertyValueDescriptor;
	}
	
	static class FieldPropertyValueDescriptor implements PropertyValueDescriptor
	{
		private Field field;
		
		@Override
		public void initialize(Class<?> beanType, String propertyName)
		{
			for (Field each : Commons.getAllFields(beanType))
			{
				if (each.getName().equals(propertyName))
				{
					field = each;
					field.setAccessible(true);
				}
			}
			if (field == null)
			{
				ValidationException validationException = new ValidationException(StringUtil.format("无法找到类:{}的中属性:{}", beanType.getName(), propertyName));
				throw validationException;
			}
		}
		
		@Override
		public Object propertyValue(Object bean)
		{
			try
			{
				return field.get(bean);
			}
			catch (Exception e)
			{
				throw new ValidationException(e);
			}
		}
	}
}
